<template>
  <el-cascader
    id="address-cascader"
    ref="cascader"
    v-model="selectIds"
    clearable
    filterable
    placeholder="请选择地址"
    :options="regionTree"
    :props="{
      checkStrictly: isCheckStrictly,
      multiple: multiple,
    }"
    @change="handleChange"
    @focus="handleFocus"
  >
  </el-cascader>
</template>

<script>
import region from "./region.json";
import { cloneDeep } from "lodash-es";
export default {
  props: {
    // 选择地址的等级、1表示只会显示省、2表示显示省市、3表示显示省市区、4表示显示省市区街道
    level: {
      type: Number | String,
      default: 3,
    },
    isCheckStrictly: {
      type: Boolean,
      default: false,
    },
    multiple: {
      type: Boolean,
      default: false,
    },
    value: {
      type: Array,
      default: () => [],
    },
    // 是否显示全部选项
    showAllLevels: {
      type: Boolean,
      default: true,
    },
    index: {
      type: Number,
    },
    mark: {
      //传过来的标识
      type: Object,
      default: () => null,
    },
    addressList: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      regionTree: [],
      selectIds: [],
    };
  },
  watch: {
    addressList: {
      handler(val) {
        if (val&&val.some((item) => item)) {
          val = val.filter(
            (item) =>
              (Array.isArray(item) && item.length) ||
              (!Array.isArray(item) && item)
          ); //先把空的去掉
          if (this.multiple) {
            this.selectIds = val.map((item) =>
              item
                .filter((item2) => typeof item2 === "number")
                .slice(0, this.level)
            );
            this.names = val.map((item) =>
              item
                .filter((item2) => typeof item2 === "string" && item)
                .slice(0, this.level)
            );
          } else {
            this.selectIds = val
              .filter((item) => typeof item === "number")
              .slice(0, this.level);
            this.names = val
              .filter((item) => typeof item === "string")
              .slice(0, this.level);
          }
          // 如果有地区名字传过来那么就用名字和id作为cascader的options，这个是在编辑的时候用的
          // 在编辑的时候需要展示地区数据，所有要通过传过来的id和名字组成options
          if (this.names.length > 0 && !this.flag && !this.multiple) {
            this.regionTree = this.arrToTree([this.selectIds, this.names]);
          } else if (
            (this.names.length == 0 && !this.flag) ||
            (!this.flag && this.multiple)
          ) {
            this.handleFocus();
          }
        } else {
          this.selectIds = [];
        }
      },
      immediate: true,
    },
  },
  mounted() {
    // 多选的时候会有bug，监听不到聚焦事件
    const el = document.querySelector("#address-cascader");
    const el2 = document.querySelector(".el-cascader__search-input");
    el && el.addEventListener("click", this.handleFocus);
    el2 && el2.addEventListener("focus", this.handleFocus);
  },
  methods: {
    handleFocus() {
      // 用flag表示只会赋值一次这个数据
      if (this.flag) return;
      setTimeout(() => {
        // 开启定时，获取数据，否则下拉会卡顿一下才显示出来
        this.regionTree = cloneDeep(region.data);
        this.removeChildren(this.regionTree, this.level);
        this.flag = true;
      }, 150);
    },
    handleChange(e) {
      this.$nextTick(() => {
        // 这里一定要先调用nextTick方法，否则获取到的还是原来的
        let node = this.$refs.cascader.getCheckedNodes();
        if (this.multiple) {
          node = { list: node.map((item) => this.formatNode(item)) };
        } else {
          node = this.formatNode(node[0]);
        }
        // 如果有索引标识传过来也传过去
        if (this.index || this.index === 0) node.index = this.index;
        // 如果有其它标识传过来也传过去
        if (this.mark) node.mark = this.mark;
        this.$emit("getAddress", node);
      });
    },
    // 父组件传过来的值通过调用这个方法来格式化成cascader组件的options
    arrToTree(idNameList, arr = [], index = 0) {
      arr.push({
        value: idNameList[0][index],
        label: idNameList[1][index],
      });
      if (index !== idNameList.length - 1) {
        this.arrToTree(idNameList, (arr.children = []), index + 1);
      }
      return arr;
    },
    /* 
            移除最后的子节点
        */
    removeChildren(arr, level) {
      if (!arr || arr.length == 0) return;
      level--;
      if (level == 0) {
        arr.forEach((item) => {
          if (item.hasOwnProperty("children")) delete item.children;
        });
      } else {
        arr.forEach((item) => {
          if (item.children) {
            this.removeChildren(item.children, level);
          } else {
            delete item.children;
          }
        });
      }
    },
    /* 
            把选中节点的值格式化
        */
    formatNode(node, obj, levels = 0) {
      if (!obj) {
        obj = {};
        switch (this.level) {
          case 4:
            obj.streetId = "";
            obj.streetName = "";
          case 3:
            obj.areaId = "";
            obj.areaName = "";
          case 2:
            obj.cityId = "";
            obj.cityName = "";
          case 1:
            obj.provinceId = "";
            obj.provinceName = "";
        }
      }

      if (!node) return obj;

      levels++;

      switch (node.level) {
        case 1:
          obj.provinceId = node.value;
          obj.provinceName = node.label;
          break;
        case 2:
          obj.cityId = node.value;
          obj.cityName = node.label;
          break;
        case 3:
          obj.areaId = node.value;
          obj.areaName = node.label;
          break;
        case 4:
          obj.streetId = node.value;
          obj.streetName = node.label;
          break;
      }

      if (node.parent) {
        this.formatNode(node.parent, obj, levels);
      } else {
        obj.levels = levels;
      }
      return obj;
    },
  },
};
</script>

<style lang="scss" scoped></style>
